package com.rainbowred.api.controller;

import com.alibaba.fastjson.JSONObject;
import com.rainbowred.common.controller.BaseController;
import com.rainbowred.common.enums.ErrorCode;
import com.rainbowred.common.execption.BusinessException;
import com.rainbowred.common.pojo.CommonResult;
import com.rainbowred.common.util.OkHttpUtils;
import com.rainbowred.common.util.StringUtil;
import com.rainbowred.common.util.aes.AESEncodingUtil;
import com.rainbowred.common.util.aes.AesException;
import com.rainbowred.common.util.aes.SHA1;
import com.rainbowred.system.domain.EdpDeveloper;
import com.rainbowred.system.service.EdpDeveloperService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * @Desc: 调试接口
 * @Date: 2023/11/1 10:53
 * @Author: pengweibiao
 **/
@RestController
@RequestMapping("/debug")
@Slf4j
public class TestApiController extends BaseController {

    private static String url = "%6$s?" +
            "devId=%1$s" +
            "&tm=%2$s" +
            "&nonce=%3$s" +
            "&signature=%4$s" +
            "&code=%5$s";

    @Autowired
    private EdpDeveloperService service;

    /**
     * 文档页前端 接口请求
     * @param param
     * @return
     */
    @GetMapping("")
    public CommonResult<Object> validCode(@RequestParam Map<String, String> param) {
        // 校验参数
        validParam(param);
        // 获取开发者Id
        String devId = param.get("devId");
        // 查询数据
        EdpDeveloper developer = service.getById(devId);
        // 查询为空
        if (Objects.isNull(developer)) {
            throw new BusinessException(ErrorCode.E2001, "devId查询为空,联系管理员");
        }
        // 校验signature
        validSignature(developer.getToken(), param);

        // 解密
        JSONObject data = decode(developer, param.get("code"));

        log.info("=====ApiController-validCode=====data====="+data.toJSONString());

        // 业务平台Url
        String serverUrl = (String) data.get("serverUrl");
        // 校验 serverUrl
        validServerUrl(serverUrl);

        // 自定义状态参数
        Object state = data.get("state");
        // 构建请求体
        Map<String, Object> body = null;
        if (Objects.nonNull(state)) {
            body = new HashMap<>();
            body.put("state", state);
        }

        // 请求业务服务器
        String response = OkHttpUtils.builder(10).url(serverUrl).post(JSONObject.toJSONString(body)).sync();

        log.info("=====ApiController-validCode=====response====="+response);

        // 校验返回格式
        JSONObject resJson = validResponseFormat(response);

        // 页面配置
        Object config = data.get("config");

        Map<String, Object> result = new HashMap<>();
        result.put("config", config);
        result.put("data", resJson.get("data"));

        return success(result);
    }

    @PostMapping("/signature")
    public CommonResult<Object> signature(@RequestBody Map<String, String> param) {

        String token = param.get("token");
        if (StringUtil.isEmpty(token)) {
            throw new BusinessException(ErrorCode.E1001, "参数token为空");
        }
        String tm = param.get("tm");
        if (StringUtil.isEmpty(tm)) {
            throw new BusinessException(ErrorCode.E1001, "参数tm为空");
        }
        String nonce = param.get("nonce");
        if (StringUtil.isEmpty(nonce)) {
            throw new BusinessException(ErrorCode.E1001, "参数nonce为空");
        }

        String signature = getSignature(token, tm, nonce);
        Map<String, String> result = new HashMap<>();
        result.put("signature", signature);
        return success(result);
    }

    @PostMapping("/encode")
    public CommonResult<Object> encode(@RequestBody Map<String, String> param) {
        EdpDeveloper developer = validCodingInfo(param);
        String encode = encode(developer, param.get("data"));
        Map<String, String> result = new HashMap<>();
        result.put("code", encode);
        return success(result);
    }

    @PostMapping("/decode")
    public CommonResult<Object> decode(@RequestBody Map<String, String> param) {
        EdpDeveloper developer = validCodingInfo(param);
        JSONObject decode = decode(developer, param.get("data"));
        return success(decode);
    }



    /**
     * 校验参数
     * @param param
     */
    private void validParam(Map<String, String> param) {
        if (StringUtil.isEmpty(param.get("devId"))) {
            throw new BusinessException(ErrorCode.E1001, "参数devId为空");
        }
        if (StringUtil.isEmpty(param.get("tm"))) {
            throw new BusinessException(ErrorCode.E1001, "参数tm为空");
        }
        if (StringUtil.isEmpty(param.get("nonce"))) {
            throw new BusinessException(ErrorCode.E1001, "参数nonce为空");
        }
        if (StringUtil.isEmpty(param.get("signature"))) {
            throw new BusinessException(ErrorCode.E1001, "参数signature为空");
        }
        if (StringUtil.isEmpty(param.get("code"))) {
            throw new BusinessException(ErrorCode.E1001, "参数code为空");
        }
    }

    /**
     * 根据传入的参数 生成signature 校验
     * @param param 传入参数
     */
    private void validSignature(String token, Map<String, String> param) {
        // 校验signature
        if (!validSignature(token, param.get("signature"), param.get("tm"), param.get("nonce"))) {
            throw new BusinessException(ErrorCode.E1002);
        }
    }

    /**
     * 校验传入的url是否合法
     * @param serverUrl
     */
    private void validServerUrl(String serverUrl) {
        if (!serverUrl.startsWith("https://") && !serverUrl.startsWith("http://")) {
            throw new BusinessException(ErrorCode.E2003);
        }
    }

    /**
     * 校验业务服务器返回格式
     * @param response
     * @return
     */
    private JSONObject validResponseFormat(String response) {
        // 转JSON对象
        JSONObject jsonObject = JSONObject.parseObject(response);
        // 判断返回码
        Integer code = (Integer) jsonObject.get("code");
        if (Objects.isNull(code)) {
            throw new BusinessException(ErrorCode.E3002, "code字段不存在");
        }
        if (!code.equals(200)) {
            String msg = (String) jsonObject.get("msg");
            throw new BusinessException(ErrorCode.E3002, "返回错误code："+ code + (msg == null ? "" : msg));
        }

        // 判断返回数据
        Object data = jsonObject.get("data");
        if (Objects.isNull(data)) {
            throw new BusinessException(ErrorCode.E3002, "data返回为空");
        }
        return jsonObject;
    }

    /**
     * Code解密
     * @param developer 开发者信息
     * @param code 密文
     * @return
     */
    private JSONObject decode(EdpDeveloper developer, String code) {
        // 获取解密参数
        String appid = developer.getAppid();
        String aeskey = developer.getAeskey();
        String token = developer.getToken();
        if (StringUtil.isEmpty(code)) {
            throw new BusinessException(ErrorCode.E1001, "传入密文为空");
        }
        try {
            if (code.contains(" ")) {
                code = code.replace(" ", "+");
            }
            // 解密
            String s = AESEncodingUtil.jsonDecrypt(code, appid, aeskey, token);
            return JSONObject.parseObject(s);
        }catch (AesException e) {
            throw new BusinessException(ErrorCode.E2002);
        }
    }

    /**
     * Data加密
     * @param developer 开发者信息
     * @param data 明文
     * @return
     */
    private String encode(EdpDeveloper developer, String data) {
        // 获取解密参数
        String appid = developer.getAppid();
        String aeskey = developer.getAeskey();
        String token = developer.getToken();
        try {
            if (StringUtil.isEmpty(data)) {
                throw new BusinessException(ErrorCode.E1001, "明文数据为空");
            }
            // 加密
            return AESEncodingUtil.jsonEncrypt(data, appid, aeskey, token);
        }catch (AesException e) {
            throw new BusinessException(ErrorCode.E2002);
        }
    }

    /**
     * 检查AES加解密餐素
     * @param param 传入的参数
     * @return
     */
    private EdpDeveloper validCodingInfo(Map<String, String> param) {
        String appid = param.get("appid");
        String aeskey = param.get("aeskey");
        String token = param.get("token");
        if (StringUtil.isEmpty(appid)) {
            throw new BusinessException(ErrorCode.E1001, "参数appid为空");
        }
        if (StringUtil.isEmpty(aeskey)) {
            throw new BusinessException(ErrorCode.E1001, "参数aeskey为空");
        }
        if (StringUtil.isEmpty(token)) {
            throw new BusinessException(ErrorCode.E1001, "参数token为空");
        }
        return new EdpDeveloper(appid, aeskey, token);

    }


    /**
     * ==================== 模拟业务系统 ====================
     */


    /**
     * 生成文档链接 URL 方法
     * @param param
     * @return
     */
    @PostMapping("/getUrl")
    public CommonResult<Map<String, String>> produceUrl(@RequestBody Map<String, String> param) {
        log.info("=====ServerApiController-produceUrl=====pojo====="+JSONObject.toJSONString(param));
        // 平台分配的开发者信息
//        String devId = "0784DABAFA";
        String devId = param.get("devId");
//        String token = "Y1EegrI8";
//        String aeskey = "CnfKKa2n8IKZ44vAJZl65Dc7H8G7TJmz9H4s7TGByZv";
//        String appid = "BHVDE5HRYZD2IZIHTOJPITKGDM1NVFTJ";

        // 校验并 获取开发者信息
        EdpDeveloper edpDeveloper = validCodingInfo(param);

        if (StringUtil.isEmpty(devId)) {
            throw new BusinessException(ErrorCode.E1001, "参数devId为空");
        }


        // 获取传入的文档URL
        String docViewUrl = param.get("url");
        if (StringUtil.isEmpty(docViewUrl)) {
            throw new BusinessException(ErrorCode.E1001, "输入的文档应用Url为空");
        }

        // 服务接口地址
//        String serverUrl = "http://127.0.0.1:3516/api/service/service?a=1&b=2";
        String serverUrl = param.get("serverUrl");
        if (StringUtil.isEmpty(serverUrl)) {
            throw new BusinessException(ErrorCode.E1001, "参数serverUrl为空");
        }

        // 生成随机字符和时间戳
        String nonce = AESEncodingUtil.getNonce(8);
        String timeStamp = Long.toString(System.currentTimeMillis());

        // 生成SHA1加密 signature
        String signature = SHA1.getSHA1( param.get("token"), timeStamp, nonce);

        // 构建 原数据
        String json = structJson(serverUrl);
        // 原数据加密
        String code = encode(edpDeveloper, json);

        Map<String, String> result = new HashMap<>();
        result.put("url", String.format(url, devId, timeStamp, nonce, signature, code, docViewUrl));
        // 生成文档 URL链接
        return success(result);
    }

    /**
     * 返回业务数据
     * @param param 自定义GET参数
     * @param body 自定义POST参数
     * @return
     */
    @PostMapping("/service")
    public Map<String, Object> serviceApi(@RequestParam Map<String, String> param,
                                          @RequestBody Map<String, Object> body) {
        System.out.println("param:\n"+ JSONObject.toJSONString(param));
        System.out.println("body:\n"+JSONObject.toJSONString(body));

        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        List<Map<String, Object>> maps = produceData();
        result.put("data", maps);

        return result;
    }

    /**
     * 构建请求体
     * @return
     */
    private String structJson(String serverUrl) {

        Map<String, Object> result = new HashMap<>();
        result.put("serverUrl", serverUrl);

        Map<String, Object> state = new HashMap<>();
        state.put("isValue", false);
        state.put("business", "xxxxx");
        result.put("state", state);

        Map<String, Object> config = new HashMap<>();

        Map<String, Object> header = new HashMap<>();
        Map<String, String> logo = new HashMap<>();
        logo.put("img", "");
        logo.put("src", "");
        Map<String, Object> title = new HashMap<>();
        title.put("show", true);
        title.put("data", "xxx");
        header.put("logo", logo);
        header.put("title", title);

        Map<String, Object> main = new HashMap<>();
        Map<String, Boolean> menus = new HashMap<>();
        menus.put("show", true);
        Map<String, Object> content = new HashMap<>();
        content.put("title", "xxx");
        content.put("anchor", true);
        main.put("menus", menus);
        main.put("content", content);

        Map<String, Object> footer = new HashMap<>();
        footer.put("text", false);

        config.put("header", header);
        config.put("main", main);
        config.put("footer", footer);

        result.put("config", config);

        List<Map<String, Object>> maps = produceData();
        result.put("data", maps);

        return JSONObject.toJSONString(result);
    }


    /**
     * 构建模拟业务数据
     * @return
     */
    private List<Map<String, Object>> produceData() {
        List<Map<String, Object>> result = new ArrayList<>();

        List<Map<String, Object>> bmw = new ArrayList<>();
        Map<String, Object> databmw = new HashMap<>();
        databmw.put("titile", "BMW");
        databmw.put("content", "Bavarian Engine Factory Co., Ltd.");
        databmw.put("children", bmw);

        List<Map<String, String>> children7 = new ArrayList<>();
        Map<String, Object> The7 = new HashMap<>();
        The7.put("tittle", "The 7");
        The7.put("content", "MODELS OF THE NEW BMW 7 SERIES SEDAN.");
        The7.put("children", children7);

        Map<String, String> qi1 = new HashMap<>();
        qi1.put("title", "735i");
        qi1.put("content", "Pure Excellence");
        Map<String, String> qi2 = new HashMap<>();
        qi2.put("title", "735i");
        qi2.put("content", "M Sport Pro");
        Map<String, String> qi3 = new HashMap<>();
        qi3.put("title", "740i");
        qi3.put("content", "Two-Tone Oxide Grey metallic");
        Map<String, String> qi4 = new HashMap<>();
        qi4.put("title", "750i");
        qi4.put("content", "Two-Tone Black Sapphire metallic");
        children7.add(qi1);
        children7.add(qi2);
        children7.add(qi3);
        children7.add(qi4);

        List<Map<String, String>> children5 = new ArrayList<>();
        Map<String, Object> The5 = new HashMap<>();
        The5.put("tittle", "The 5");
        The5.put("content", "THE NEW BMW 5 SERIES SEDAN.");
        The5.put("children", children5);

        Map<String, String> wu1 = new HashMap<>();
        wu1.put("title", "petrol");
        wu1.put("content", "8.1s");
        Map<String, String> wu2 = new HashMap<>();
        wu2.put("title", "i5 40L");
        wu2.put("content", "6.0s");
        Map<String, String> wu3 = new HashMap<>();
        wu3.put("title", "i5 M60");
        wu3.put("content", "3.8");
        children5.add(wu1);
        children5.add(wu2);
        children5.add(wu3);

        bmw.add(The7);
        bmw.add(The5);

        result.add(databmw);

        return result;
    }


}
